home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
476-500
/
disk_500
/
wiconify
/
wiconify-source.lzh
/
Source
/
wFileRead.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-19
|
21KB
|
710 lines
/*
* WICONIFY A utility that allows you to iconify any Intuition window
* on any screen, and to open WB windows on any screen.
*
* wFileRead.c Performs most of the structured file IO.
*
* Copyright 1990 by Davide P. Cervone, all rights reserved.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "wFile.h"
#include "wMenu.h"
extern int ScreenType;
extern UWORD ImageData[MAXWORDS][MAXHEIGHT][MAXDEPTH];
extern short MaxWidth,MaxHeight,MaxWords;
extern UBYTE Plane0,Plane1;
extern int ImageType;
extern int IconFileOpen;
static int NoMaskError; /* FALSE if a mask error was reported */
static short ErrorCount; /* number of error messages so far */
#define MAXERROR 8 /* maximum number of errors in a line */
/*
* Macros for working with HEX and Color values
*/
#define HEXCHAR(c) (((c)>='0'&&(c)<='9')||((c)>='A'&&(c)<='F'))
#define VALIDCOLOR(w)\
(HEXCHAR(w[0])&&HEXCHAR(w[1])&&HEXCHAR(w[2])&&w[3]==0)
#define HEX(c) (((c)>'9')?(c)-'A'+10:(c)-'0')
#define RGB(r,g,b) ((r<<8)|(g<<4)|b)
#define COLOR(w) RGB(HEX(w[0]),HEX(w[1]),HEX(w[2]))
/*
* Allowable HEX codes
*/
static char *ExtHex = "0123456789abcdef)!@#$%^&*(ABCDEF";
/*
* The initialization file command keywords
*/
static char *MainCommand[] =
{
"", /* No command given */
"Iconify_Key", /* Sets the key and quals that iconify a window */
"Change_Refresh", /* Sets the quals that change refresh type */
"Activation_Key", /* Sets the key and quals that activate wIconify */
"Color_Map", /* Sets the default NewScreen color map */
"Default_Flags", /* Sets the default icon's icon flags */
"Screen_Flags", /* Sets the default screen icon's icon flags */
"Menu_Keys", /* Sets the menu key equivalents */
"Ignore_Screen", /* Adds screen titles to be ignored by wIconify */
"Priority", /* Sets the wIconify process priority */
"HiRes_CLICommand", /* Sets the HIRES NewCLI command string */
"LoRes_CLICommand", /* Sets the LOWRES NewCLI command string */
"Default_Image", /* Defines the default icon image */
"Default_Select", /* Defines the default icon select image */
"Default_Mask", /* Defines the default icon image mask */
"Default_Icon", /* Reads the default icon from a file */
"Screen_Image", /* Defines the default screen icon image */
"Screen_Select", /* Defines the default screen icon select image */
"Screen_Mask", /* Defines the default screen icon image mask */
"Screen_Icon", /* Reads the default screen icon from a file */
"Open_On", /* Sets the OpenOn window submenu entries */
"Size_To_Fit", /* Sets or clears the SizeToFit option */
"Command_Stack", /* Sets the size of the newCLI command stack */
"Handler_Priority", /* Sets the Input Device handler priority */
};
#define MAXMAINCOM COM_LAST
/*
* The commands for within an icon file (for DEFAULT_ICON and SCREEN_ICON)
*/
static char *IconCommand[] =
{
"Image", /* Sets the default icon image */
"Select", /* Sets the default icon select image */
"Mask" /* Sets the default icon image mask */
};
#define MAXICONCOM 2
char **ComName = &MainCommand[0]; /* The current command set */
static int ComOffset; /* Add this to get "real" command # */
static int ComCount = MAXMAINCOM; /* Size of command array */
/*
* Icon Flags for DEFAULT_FLAGS command
*/
static struct Flag IconFlag[] =
{
{"NOICONIFY", WI_NOICONIFY}, /* Window can not be iconified */
{"NOSAVEPOS", WI_NOSAVEPOS}, /* Position not saved when openned */
{"NOCLOSE", WI_NOCLOSE}, /* CLOSE menu not available */
{"NOORGANIZE", WI_NOORGANIZE}, /* Icon not affected by ORGANIZE */
{"NOMOVE", WI_NOMOVE}, /* Icon can not be moved */
{"LOCKED", WI_LOCKED}, /* Never change icon X,Y */
{"NOMULTISELECT",WI_NOMULTISELECT}, /* No more than one icon selectable */
{"CHANGEREFRESH",WI_CHANGEREFRESH}, /* Automatically change refresh type */
};
#define MAXICONFLAG 8
/*
* Qualifier key names and flags for ReadKeyDefinition()
*/
static struct Flag KeyFlag[] =
{
{"LSHIFT", IEQUALIFIER_LSHIFT},
{"RSHIFT", IEQUALIFIER_RSHIFT},
{"CAPSLOCK", IEQUALIFIER_CAPSLOCK},
{"CONTROL", IEQUALIFIER_CONTROL},
{"LALT", IEQUALIFIER_LALT},
{"RALT", IEQUALIFIER_RALT},
{"LCOMMAND", IEQUALIFIER_LCOMMAND},
{"RCOMMAND", IEQUALIFIER_RCOMMAND},
{"LAMIGA", IEQUALIFIER_LCOMMAND},
{"RAMIGA", IEQUALIFIER_RCOMMAND},
{"NUMERICPAD", IEQUALIFIER_NUMERICPAD},
{"REPEAT", IEQUALIFIER_REPEAT},
{"MBUTTON", IEQUALIFIER_MIDBUTTON},
{"RBUTTON", IEQUALIFIER_RBUTTON},
{"LBUTTON", IEQUALIFIER_LEFTBUTTON},
};
#define MAXKEYFLAG 15
/*
* Key names and numbers for ReadKeyDefinition()
*/
#define KEY(x) (x|IECODE_UP_PREFIX)
struct Flag KeyName[] =
{
{"RBUTTONPRESS", MENUUP},
{"LBUTTONPRESS", SELECTUP},
{"F1", KEY(0x50)},
{"F2", KEY(0x51)},
{"F3", KEY(0x52)},
{"F4", KEY(0x53)},
{"F5", KEY(0x54)},
{"F6", KEY(0x55)},
{"F7", KEY(0x56)},
{"F8", KEY(0x57)},
{"F9", KEY(0x58)},
{"F10", KEY(0x59)},
{"ESC", KEY(0x45)},
{"ENTER", KEY(0x43)},
{"RETURN", KEY(0x44)},
{"BACKSPACE",KEY(0x41)},
{"DELETE", KEY(0x46)},
{"HELP", KEY(0x5F)},
{"TAB", KEY(0x42)},
{"SPACE", KEY(0x40)}
};
#define MAXKEYNAME 20
/*
* Menu names and IDs
*/
struct Flag MenuName[] =
{
{"OPEN", MENUID(ICON_MENU,IM_OPEN,NOSUB)},
{"CLOSE", MENUID(ICON_MENU,IM_CLOSE,NOSUB)},
{"LOCK", MENUID(ICON_MENU,IM_LOCK,NOSUB)},
{"UNLOCK", MENUID(ICON_MENU,IM_LOCK,NOSUB)},
{"CLEAN_UP", MENUID(ICON_MENU,IM_CLEANUP,NOSUB)},
{"ORGANIZE", MENUID(ICON_MENU,IM_ORGANIZE,NOSUB)},
{"OPEN_ALL", MENUID(ICON_MENU,IM_OPENALL,NOSUB)},
{"ABOUT", MENUID(ICON_MENU,IM_ABOUT,NOSUB)},
{"END", MENUID(ICON_MENU,IM_END,NOSUB)},
{"TO_FRONT", MENUID(SCREEN_MENU,SM_TOFRONT,NOSUB)},
{"TO_BACK", MENUID(SCREEN_MENU,SM_TOBACK,NOSUB)},
{"WB_TO_FRONT", MENUID(SCREEN_MENU,SM_WBTOFRONT,NOSUB)},
{"TOGGLE_TITLE", MENUID(SCREEN_MENU,SM_TOGGLE,NOSUB)},
{"ICONIFY", MENUID(SCREEN_MENU,SM_ICONIFY,NOSUB)},
{"NEWCLI", MENUID(SCREEN_MENU,SM_NEWCLI,NOSUB)},
{"MAKE_WB", MENUID(SCREEN_MENU,SM_MAKEWB,NOSUB)},
{"ACTIVE_SCREEN", MENUID(SCREEN_MENU,SM_OPENWINDOW,OW_ACTIVESCRN)},
{"CURRENT_WB", MENUID(SCREEN_MENU,SM_OPENWINDOW,OW_CURRENTWB)},
{"REAL_WB", MENUID(SCREEN_MENU,SM_OPENWINDOW,OW_REALWB)},
{"SIZE_TO_FIT", MENUID(SCREEN_MENU,SM_OPENWINDOW,OW_AUTORESIZE)},
{"HIRES", MENUID(SCREEN_MENU,SM_NEWSCREEN,NS_HIRES)},
{"LORES", MENUID(SCREEN_MENU,SM_NEWSCREEN,NS_LORES)},
{"INTERLACE", MENUID(SCREEN_MENU,SM_NEWSCREEN,NS_INTERLACE)},
{"HAM", MENUID(SCREEN_MENU,SM_NEWSCREEN,NS_HAM)},
{"CLOSE_SCREEN", MENUID(SCREEN_MENU,SM_CLOSESCREEN,NOSUB)},
};
#define MAXMENU 25
/*
* ReadCommand()
*
* If we're at the end of the line, read the next line.
* Get the next word on the line.
* If we have readed the end of the file, use COM_EOF
* Otherwise, if the character following the next word is not ':'
* then we have not found a command, so use COM_NONE,
* Otherwise,
* Look for the command in the current command table, and skip the ':'
* Return the number of the command found.
*/
int ReadCommand()
{
int Command = COM_UNKNOWN;
short i;
if (NextChar == '\n' || NextChar == 0) ReadNextLine();
ReadNextWord();
if (EndOfFile) Command = COM_EOF; else
if (NextChar != ':') Command = COM_NONE;
else
{
for (i=0; i<=ComCount && Command == COM_UNKNOWN; i++)
if (WORDMATCH(ComName[i])) Command = i + ComOffset;
SkipChar();
}
return(Command);
}
/*
* ReadKeyDef()
*
* Parse the next word as a qualifier or key name.
* If theKey is NULL, no key name is allowed, if DisQual is NULL, no
* disqualifiers are allowed.
*
* If the next character is '\' and we are accepting key names,
* Go back to the start of the word and skip the '\'
* If the next char is a HEX digit,
* Get the HEX value of the next char and get the following char.
* If the following char is a HEX digit,
* Shift the old hex digit by 16 (10 HEX), add the next digit,
* and get the next character
* Skip any blanks.
* Mark the code as a key-up event
* Otherwise give an error message.
* Indicate that this should be the end of the line.
* Otherwise (not a '\')
* If the word is '+' or '|', ie, a qualifier, then
* If there were no qualifiers or disqualifiers given, give a message
* Get the next word (the qualifier itself)
* Otherwise, if the word is '-', ie, a disqualifier, then
* Check to make sure disqualifiers are allowed; error if not.
* Get the disqualifier.
* Look through the qualifier flag names for a match.
* If a match is found,
* add the qualifier to the proper list and end the loop
* If no qualifier was found,
* If we are allowed to have a key name,
* Go back to the beginning of the word, and re-read it allowing numbers
* Look through the key name list
* If a match is found,
* Record the key number and end the loop.
* Indicate that this should be the end of the line.
* If no match found, give an error.
* Otherwise (no key name allowed) give an error.
* Return the end-of-line status.
*/
int ReadKeyDef(theKey,theQual,DisQual)
UBYTE *theKey;
USHORT *theQual,*DisQual;
{
short i;
int AddIt = TRUE;
int EndOfLine = FALSE;
int OpMissing;
if (Word[0] == '\\' && theKey)
{
Reread(); GetNextChar();
if (HEXCHAR(NextChar))
{
*theKey = HEX(NextChar);
GetNextChar();
if (HEXCHAR(NextChar))
{
*theKey = 16*(*theKey) + HEX(NextChar);
GetNextChar();
}
SkipSpaces();
*theKey |= IECODE_UP_PREFIX;
} else Expected("HEX char");
EndOfLine = TRUE;
} else {
if (Word[0] == '+' || Word[0] == '|')
{
if (*theQual == 0)
{
if (DisQual == NULL) OpMissing = TRUE; else
if (*DisQual == 0) OpMissing = TRUE; else OpMissing = FALSE;
if (OpMissing) ShowError("Missing Qualifier before '%c'",Word[0]);
}
ReadNextWord();
} else if (Word[0] == '-') {
if (DisQual) AddIt = FALSE; else
ShowError("Disqualifiers not allowed");
ReadNextWord();
}
for (i=0; i<MAXKEYFLAG; i++)
{
if (WORDMATCH(KeyFlag[i].Name))
{
if (AddIt) *theQual |= KeyFlag[i].Flag;
else *DisQual |= KeyFlag[i].Flag;
i = MAXKEYFLAG+1;
}
}
if (i == MAXKEYFLAG)
{
if (theKey)
{
Reread(); ReadExtendedWord();
for (i=0; i<MAXKEYNAME; i++)
{
if (WORDMATCH(KeyName[i].Name))
{
*theKey = KeyName[i].Flag;
i = MAXKEYNAME+1;
EndOfLine = TRUE;
}
}
if (i == MAXKEYNAME) Expected("a Key-Name or Qualifier");
} else Expected("a Qualifier");
}
}
return(EndOfLine);
}
/*
* ReadColor()
*
* If the color number is a valid one,
* Go back to the beginning of the word and read it as a number.
* Set it to upper case (for HEX check).
* If the word is '=', set the color value to NOCOLOR
* If the color is a valid color specification, get the color value
* If the color is '*' leave the color alone,
* Otherwise, give an error.
* Otherwise give an error about how many colors are allowed.
*/
void ReadColor(theID)
short theID;
{
extern UWORD *ScreenColors;
if (theID < 32)
{
Reread(); ReadExtendedWord(); WordToUpper();
if (WORDMATCH("=")) ScreenColors[theID] = NOCOLOR; else
if (VALIDCOLOR(Word)) ScreenColors[theID] = COLOR(Word); else
if (WORDMATCH("*") == FALSE) Expected("an RGB Color");
} else ShowError("Maximum of 32 colors exceeded");
}
/*
* ReadIconFlags()
*
* If the word is '+' or '|', then
* If there were no previous flags specified, give an error
* The next word is the flag name
* Look through the flag names
* If one of them matches,
* Add the flag to the default flags and end the loop
* If no flag found, give an error.
*/
void ReadIconFlags(Flags)
long *Flags;
{
short i;
if (Word[0] == '|' || Word[0] == '+')
{
if (*Flags == 0)
ShowError("Missing Icon Flag before '%c'",Word[0]);
ReadNextWord();
}
for (i=0; i<MAXICONFLAG; i++)
{
if (WORDMATCH(IconFlag[i].Name))
(*Flags) |= IconFlag[i].Flag,
i = MAXICONFLAG+1;
}
if (i == MAXICONFLAG) Expected("an Icon Flag");
}
/*
* ReadMenuKey()
*
* Look through the menu names
* If one of them matches,
* Get the pointer to the specified item in the menu bar structure;
* If there is no command key, clear the COMSEQ flag for the item,
* Otherwise,
* Get the next word and make it upper case
* If it is a control character, report an error;
* If it is more than one characterm report an error;
* Otherwise, set the command key to the indicated one.
* End the loop.
* If no match was found, give an error, and skip the rest of the line.
*/
void ReadMenuKey()
{
short i;
struct MenuItem *theItem;
extern struct MenuItem *ItemAddress();
extern struct Menu *wMenuBar;
for (i=0; i<MAXMENU; i++)
{
if (WORDMATCH(MenuName[i].Name))
{
theItem = ItemAddress(wMenuBar,MenuName[i].Flag);
if (NextChar == '\n')
{
theItem->Flags &= ~COMMSEQ;
theItem->Command = 0;
} else {
ReadNextWord(); WordToUpper();
if (Word[0] < ' ') Expected("a Printable Character"); else
if (Word[1] != 0) Expected("a Single Character");
else theItem->Flags |= COMMSEQ, theItem->Command = Word[0];
}
i = MAXMENU+1;
}
}
if (i == MAXMENU)
{
if (strlen(Word) > 1) ShowError("Unrecognized Menu '%s'",Word);
else Expected("a Menu Item Name");
SkipLine();
}
}
/*
* ReadBool()
*
* If the word is "TRUE", return TRUE.
* If the word is "FALSE", return FALSE.
* Otherwise, give an error.
*/
void ReadBool(n)
int *n;
{
if (WORDMATCH("TRUE")) *n = TRUE; else
if (WORDMATCH("FALSE")) *n = FALSE; else
Expected("TRUE or FALSE");
}
/*
* ReadInteger()
*
* Parse the next word as an integer.
* If the word is an integer, return it, otherwise give an error.
*/
void ReadInteger(i)
int *i;
{
ReadNextInteger();
if (sscanf(Word,"%d",i) != 1) Expected("Integer value");
}
/*
* ReadString()
*
* Get the whole line as the next word.
* If the character string has already been read, free it.
* Get enough space for the new string, and copy the value into it.
* Of not enough space, give an error.
*/
void ReadString(s)
char **s;
{
ReadFullLine();
if (*s) FREECHAR(*s);
if (NEWCHAR(*s,strlen(Word))) strcpy(*s,Word); else
ShowError("Can't get memory for character string");
}
/*
* ReadIgnoreScreen()
*
* Get a new Ignore structure; if allocated OK,
* Read the title of the screen.
* If a title was found, add the screen to the ignored list,
* Otherwise, free the Ignore structure.
* Otherwise, give an error and skip the rest of the line.
*/
void ReadIgnoreScreen()
{
struct Ignore *theScreen;
if (NEWSTRUCT(Ignore,theScreen))
{
ReadString(&theScreen->Title);
if (theScreen->Title)
{
theScreen->Next = IgnoreScreen;
IgnoreScreen = theScreen;
} else {
FREESTRUCT(Ignore,theScreen);
}
} else {
ShowError("Can't get memory to Ignore Screen");
SkipLine();
}
}
/*
* GetPen()
*
* Look for the given HEX digit in the extended HEX list.
* If not found,
* Give an error message and count the number of errors.
* If more than the maximum allowed, skip the rest of the line.
* If the image type is a MASK, and the pen is not 0 or 1,
* If there were no previous errors of this type, give one.
* Mark that the user was warned about mask pen types.
* Reduce the pen number to 0 or 1.
* Return the pen color.
*/
static UBYTE GetPen(c)
char c;
{
UBYTE Pen = 0;
short i;
for (i=0; i<32; i++) if (c == ExtHex[i]) Pen = i, i = 33;
if (i == 32)
{
Expected("HEX Digit"); ErrorCount++;
if (ErrorCount > MAXERROR)
printf("Maximum errors exceeded - skipping rest of line\n"),
SkipLine();
}
if (Pen > 1 && (ImageType == COM_DEFAULTMASK || ImageType == COM_SCREENMASK))
{
if (NoMaskError) ShowError("Mask pixel values must be 0 or 1");
NoMaskError = FALSE;
Pen = Pen & 1;
}
return(Pen);
}
/*
* ReadImageLine()
*
* If the current line is within the maximum image size,
* Clear the error flags, and get back to the beginning of the line.
* While we're not at the end of the line,
* If the current column is within the maximum image size,
* Get the pen number of the current pixel, and increment the column.
* Update Plane0 and Plane1 (Plane0 has a zero wherever that plane
* has at least one pixel that is zero; Plane1 has a 1 wherever
* that plane has at least one pixel that is one).
* If the bit mask has wrapped around, go on to the next image word.
* For each 1 bit in the Pen color, add a 1 bit into the image data
* Shift the image mask to the right.
* Get the next pixel's pen color and skip any comments.
* Skip trailing blanks (but not interior blanks).
* Otherwise, indicate that the width is too large and skip to the
* end of the line.
* Update the current image size, if necessary.
* Otherwise, indicate that the icon is too tall, and skip to the next line.
*/
void ReadImageLine(y)
short y;
{
short x = 0, w = 0;
short d;
UWORD mask = BIT(15);
UBYTE Pen;
if (y < MAXHEIGHT)
{
NoMaskError = TRUE; ErrorCount = 0;
Reread();
while (NextChar != '\n')
{
if (x < MAXWIDTH)
{
Pen = GetPen(NextChar); x++;
Plane0 &= Pen; Plane1 |= Pen; d = 0;
if (mask == 0) w++, mask = BIT(15);
while (Pen)
{
if (Pen & 1) ImageData[w][y][d] |= mask;
Pen >>= 1; d++;
}
mask >>= 1;
GetNextChar(); SkipComments();
if (NextChar == ' ')
{
SkipSpaces();
if (NextChar != '\n') Reread();
}
} else {
ReadFullLine();
ShowError("Maximum Image Width of %d exceeded",MAXWIDTH);
}
}
if (x > MaxWidth) MaxWidth = x, MaxWords = w+1;
if (y+1 > MaxHeight) MaxHeight = y+1;
if (MaxWidth > MAXWIDTH) MaxWidth = MAXWIDTH;
} else {
ReadFullLine();
ShowError("Maxmimum Image Height of %d exceeded",MAXHEIGHT);
}
}
/*
* ReadIconFile()
*
* Get the rest of the line (it will be the file name to open)
* Save the current file information.
* Attempt to open the specified file.
* If openned OK, then
* Set the icon file flag,
* Set the command list to the icon file command list and size.
* Otherwise,
* Put back the old file information,
* Give an error about the icon file.
*/
void ReadIconFile(Offset)
int Offset;
{
ReadFullLine();
SaveOpenFile();
if (OpenFile(Word))
{
IconFileOpen = TRUE;
ComName = &IconCommand[0];
ComOffset = Offset;
ComCount = MAXICONCOM;
} else {
RestoreFile();
ShowError("Can't open Icon file '%s'",Word);
}
}
/*
* EndIconFile()
*
* Put back the old file information
* Mark the file as closed, and restore the command list to the main list.
*/
void EndIconFile()
{
RestoreFile();
IconFileOpen = FALSE;
ComName = &MainCommand[0];
ComOffset = 0;
ComCount = MAXMAINCOM;
}
/*
* ReadOpenOn()
*
* Check if the word is one of "ACTIVE_SCREEN", "CURRENT_WB", or "REAL_WB",
* and return the correct type, otherwise give an error.
*/
void ReadOpenOn()
{
if (WORDMATCH("ACTIVE_SCREEN")) ScreenType = OW_ACTIVESCRN; else
if (WORDMATCH("CURRENT_WB")) ScreenType = OW_CURRENTWB; else
if (WORDMATCH("REAL_WB")) ScreenType = OW_REALWB; else
Expected("ACTIVE_SCREEN, CURRENT_WB, or REAL_WB");
}